@use 'sass:map';
@use '@material/card' as mdc-card;
@use '@material/card/elevated-card-theme' as mdc-elevated-card-theme;
@use '@material/card/outlined-card-theme' as mdc-outlined-card-theme;
@use '@material/theme/custom-properties' as mdc-custom-properties;
@use '../core/tokens/token-utils';
@use '../core/tokens/m2/mat/card' as tokens-mat-card;
@use '../core/tokens/m2/mdc/elevated-card' as tokens-mdc-elevated-card;
@use '../core/tokens/m2/mdc/outlined-card' as tokens-mdc-outlined-card;

// TODO(jelbourn): move header and title-group styles to their own files.
@include mdc-custom-properties.configure($emit-fallback-values: false, $emit-fallback-vars: false) {
  $mdc-elevated-card-token-slots: tokens-mdc-elevated-card.get-token-slots();
  $mdc-outlined-card-token-slots: tokens-mdc-outlined-card.get-token-slots();

  // Add the MDC card static styles.
  @include mdc-card.static-styles();

  .mat-mdc-card {
    // Add the official slots for the MDC elevated-card.
    @include mdc-elevated-card-theme.theme-styles(map.merge($mdc-elevated-card-token-slots, (
      // MDC emits the box-shadow on .mdc-card, so the full selector would be
      // `.mat-mdc-card .mdc-card` which is incorrect. We emit the elevation slot ourselves instead.
      container-elevation: null,
      container-shadow-color: null,
    )));

    // Emit the elevation slot directly on .mat-mdc-card.
    @include token-utils.use-tokens(
        tokens-mdc-elevated-card.$prefix, $mdc-elevated-card-token-slots) {
      @include token-utils.create-token-slot(box-shadow, container-elevation);
    }
  }

  .mat-mdc-card-outlined {
    // Add the official slots for the MDC outlined-card.
    @include mdc-outlined-card-theme.theme-styles(map.merge($mdc-outlined-card-token-slots, (
      // MDC emits the box-shadow on .mdc-card, so the full selector would be
      // `.mat-mdc-card-outlined .mdc-card` which is incorrect. We emit the elevation slot ourselves
      // instead.
      container-elevation: null,
      container-shadow-color: null,
    )));

    // Emit the elevation slot directly on .mat-mdc-card-outlined.
    @include token-utils.use-tokens(
        tokens-mdc-outlined-card.$prefix, $mdc-outlined-card-token-slots) {
      @include token-utils.create-token-slot(box-shadow, container-elevation);
    }
  }

  // Add slots for custom Angular Material card tokens.
  @include token-utils.use-tokens(tokens-mat-card.$prefix, tokens-mat-card.get-token-slots()) {
    .mat-mdc-card-title {
      @include token-utils.create-token-slot(font-family, title-text-font);
      @include token-utils.create-token-slot(line-height, title-text-line-height);
      @include token-utils.create-token-slot(font-size, title-text-size);
      @include token-utils.create-token-slot(letter-spacing, title-text-tracking);
      @include token-utils.create-token-slot(font-weight, title-text-weight);
    }

    .mat-mdc-card-subtitle {
      @include token-utils.create-token-slot(color, subtitle-text-color);
      @include token-utils.create-token-slot(font-family, subtitle-text-font);
      @include token-utils.create-token-slot(line-height, subtitle-text-line-height);
      @include token-utils.create-token-slot(font-size, subtitle-text-size);
      @include token-utils.create-token-slot(letter-spacing, subtitle-text-tracking);
      @include token-utils.create-token-slot(font-weight, subtitle-text-weight);
    }
  }
}

// Size of the `mat-card-header` region custom to Angular Material.
$mat-card-header-size: 40px !default;

// Default padding for text content within a card.
$mat-card-default-padding: 16px !default;

.mat-mdc-card {
  position: relative;
}

// Title text and subtitles text within a card. MDC doesn't have pre-made title sections for cards.
// Maintained here for backwards compatibility with the previous generation MatCard.
.mat-mdc-card-title,
.mat-mdc-card-subtitle {
  // Custom elements default to `display: inline`. Reset to 'block'.
  display: block;

  // Titles and subtitles can be set on native header elements which come with
  // their own margin. Clear it since the spacing is done using `padding`.
  margin: 0;

  .mat-mdc-card-avatar ~ .mat-mdc-card-header-text & {
    // Apply default padding for a text content region. Omit any bottom padding because we assume
    // this region will be followed by another region that includes top padding.
    padding: $mat-card-default-padding $mat-card-default-padding 0;
  }
}

// Header section at the top of a card. MDC does not have a pre-made header section for cards.
// Maintained here for backwards compatibility with the previous generation MatCard.
.mat-mdc-card-header {
  // The primary purpose of the card header is to lay out the title, subtitle, and image in the
  // correct order. The image will come first, followed by a single div that will contain (via
  // content projection) both the title and the subtitle.
  display: flex;

  // Apply default padding for the header region. Omit any bottom padding because we assume
  // this region will be followed by another region that includes top padding.
  padding: $mat-card-default-padding $mat-card-default-padding 0;
}

// Primary card content. MDC does not have a pre-made section for primary content.
// Adds the default 16px padding to the content. Maintained here for backwards compatibility
// with the previous generation MatCard.
.mat-mdc-card-content {
  // Custom elements default to `display: inline`. Reset to 'block'.
  display: block;

  // Apply default horizontal padding for a content region.
  padding: 0 $mat-card-default-padding;

  // Only add vertical padding to the main content area if it's not preceeded/followed by another
  // element within the card.
  &:first-child {
    padding-top: $mat-card-default-padding;
  }

  &:last-child {
    padding-bottom: $mat-card-default-padding;
  }
}

// Title group within a card. MDC does not have a pre-made section for anything title-related.
// Maintained here for backwards compatibility with the previous generation MatCard.
.mat-mdc-card-title-group {
  // This element exists primary to lay out its children (title, subtitle, media). The title
  // and subtitle go first (projected into a single div), followed by the media.
  display: flex;
  justify-content: space-between;
  width: 100%;
}

// Avatar image for a card. MDC does not specifically have a card avatar or a "common" avatar.
// They *do* have a list avatar, but it uses a different size than we do here, which we preserve
// to reduce breaking changes. Ultimately, the avatar styles just consist of a size and a
// border-radius.
.mat-mdc-card-avatar {
  height: $mat-card-header-size;
  width: $mat-card-header-size;
  border-radius: 50%;
  flex-shrink: 0;
  margin-bottom: $mat-card-default-padding;

  // Makes `<img>` tags behave like `background-size: cover`. Not supported
  // in IE, but we're using it as a progressive enhancement.
  object-fit: cover;

  // When a title and subtitle are used alongside an avatar,
  // reduce the spacing between them to better align with the avatar.
  & ~ .mat-mdc-card-header-text {
    .mat-mdc-card-subtitle,
    .mat-mdc-card-title {
      line-height: normal;
    }
  }
}

// Specifically sized small image, specific to Angular Material.
.mat-mdc-card-sm-image {
  width: 80px;
  height: 80px;
}

// Specifically sized medium image, specific to Angular Material.
.mat-mdc-card-md-image {
  width: 112px;
  height: 112px;
}

// Specifically sized large image, specific to Angular Material.
.mat-mdc-card-lg-image {
  width: 152px;
  height: 152px;
}

// Specifically sized extra-large image, specific to Angular Material.
.mat-mdc-card-xl-image {
  width: 240px;
  height: 240px;
}

// When both a title and a subtitle are used, eliminate the top padding of whichever comes second
// because the first already covers the padding.
//
// Additionally, reset the padding for title and subtitle when used within `mat-card-header` or
// `mat-card-title-group` since the padding is captured by parent container already.
.mat-mdc-card-subtitle ~ .mat-mdc-card-title,
.mat-mdc-card-title ~ .mat-mdc-card-subtitle,

// The `.mat-mdc-card-header-text` here is redundant since the header text
// wrapper is always there in the header, but we need the extra specificity.
.mat-mdc-card-header .mat-mdc-card-header-text .mat-mdc-card-title,
.mat-mdc-card-header .mat-mdc-card-header-text .mat-mdc-card-subtitle,
.mat-mdc-card-title-group .mat-mdc-card-title,
.mat-mdc-card-title-group .mat-mdc-card-subtitle {
  padding-top: 0;
}

// Remove the bottom margin from the last child of the card content. We intended to remove
// margin from elements that have it built-in, such as `<p>`. We do this to avoid having too much
// space between card content regions, as the space is already captured in the content region
// element.
.mat-mdc-card-content > :last-child:not(.mat-mdc-card-footer) {
  margin-bottom: 0;
}

// Support for actions aligned to the end of the card.
.mat-mdc-card-actions-align-end {
  justify-content: flex-end;
}
